package v1

import (
	"errors"
	"strconv"
	"strings"
	"wms/internal/model/request"
	"wms/internal/service"
	"wms/pkg/common"
	"wms/pkg/logger"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// CargoController 货物控制器
type CargoController struct {
	cargoService *service.CargoService
}

// NewCargoController 创建货物控制器
func NewCargoController() *CargoController {
	return &CargoController{
		cargoService: service.NewCargoService(),
	}
}

// Get godoc
// @Summary 获取货物详情
// @Description 根据货物ID获取货物详细信息
// @Tags 货物管理
// @Accept json
// @Produce json
// @Param id path int true "货物ID"
// @Success 200 {object} common.Response{data=model.Cargo} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos/{id} [get]
func (c *CargoController) Get(ctx *gin.Context) {
	id := common.GetIDParam(ctx)
	if id == 0 {
		common.Error(ctx, common.ErrInvalidParams)
		return
	}

	cargo, err := c.cargoService.GetCargo(id)
	if err != nil {
		logger.Error("获取货物详情失败", zap.Error(err), zap.Uint("id", id))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, cargo)
}

// List godoc
// @Summary 获取货物列表
// @Description 分页获取货物列表信息
// @Tags 货物管理
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Param category_id query int false "分类ID"
// @Success 200 {object} common.Response{data=[]model.Cargo} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos [get]
func (c *CargoController) List(ctx *gin.Context) {
	var req request.ListCargoRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定货物列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	cargos, total, err := c.cargoService.ListCargos(&req)
	if err != nil {
		logger.Error("获取货物列表失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	// 确保total值与实际返回的列表长度一致
	actualTotal := int64(len(cargos))
	// 如果计算出的total大于实际列表长度，且列表长度小于请求的页大小，说明已经没有更多数据
	if total > actualTotal && actualTotal < int64(req.GetPageSize()) {
		total = actualTotal + int64((req.GetPage()-1)*req.GetPageSize())
	}

	common.Success(ctx, gin.H{
		"list":  cargos,
		"total": total,
	})
}

// Create godoc
// @Summary 创建货物
// @Description 创建新的货物
// @Tags 货物管理
// @Accept json
// @Produce json
// @Param cargo body request.CreateCargoRequest true "货物信息"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos [post]
func (c *CargoController) Create(ctx *gin.Context) {
	var req request.CreateCargoRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建货物请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.cargoService.CreateCargo(&req, userID); err != nil {
		logger.Error("创建货物失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// Update godoc
// @Summary 更新货物
// @Description 更新货物信息
// @Tags 货物管理
// @Accept json
// @Produce json
// @Param cargo body request.UpdateCargoRequest true "货物信息"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos [put]
func (c *CargoController) Update(ctx *gin.Context) {
	var req request.UpdateCargoRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定更新货物请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.cargoService.UpdateCargo(&req, userID); err != nil {
		logger.Error("更新货物失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// Delete godoc
// @Summary 删除货物
// @Description 删除指定货物
// @Tags 货物管理
// @Accept json
// @Produce json
// @Param id body uint true "货物ID"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos [delete]
func (c *CargoController) Delete(ctx *gin.Context) {
	var req struct {
		ID uint `json:"id" binding:"required"`
	}

	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定删除货物请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.cargoService.DeleteCargo(req.ID, userID); err != nil {
		logger.Error("删除货物失败", zap.Error(err), zap.Uint("id", req.ID))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// ListCategories godoc
// @Summary 获取货物分类列表
// @Description 获取所有货物分类列表
// @Tags 货物分类
// @Accept json
// @Produce json
// @Param keyword query string false "搜索关键词"
// @Success 200 {object} common.Response{data=[]model.CargoCategory} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos/categories [get]
func (c *CargoController) ListCategories(ctx *gin.Context) {
	var req request.ListCargoCategoryRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定货物分类列表请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	categories, err := c.cargoService.ListCategories(&req)
	if err != nil {
		logger.Error("获取货物分类列表失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, categories)
}

// CreateCategory godoc
// @Summary 创建货物分类
// @Description 创建新的货物分类
// @Tags 货物分类
// @Accept json
// @Produce json
// @Param category body request.CreateCargoCategoryRequest true "分类信息"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos/categories [post]
func (c *CargoController) CreateCategory(ctx *gin.Context) {
	var req request.CreateCargoCategoryRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定创建货物分类请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.cargoService.CreateCategory(&req, userID); err != nil {
		logger.Error("创建货物分类失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// UpdateCategory godoc
// @Summary 更新货物分类
// @Description 更新货物分类信息
// @Tags 货物分类
// @Accept json
// @Produce json
// @Param category body request.UpdateCargoCategoryRequest true "分类信息"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos/categories [put]
func (c *CargoController) UpdateCategory(ctx *gin.Context) {
	var req request.UpdateCargoCategoryRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		logger.Warn("绑定更新货物分类请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.cargoService.UpdateCategory(&req, userID); err != nil {
		logger.Error("更新货物分类失败", zap.Error(err), zap.Any("req", req))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// DeleteCategory godoc
// @Summary 删除货物分类
// @Description 删除指定货物分类
// @Tags 货物分类
// @Accept json
// @Produce json
// @Param id path int true "分类ID"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos/categories/{id} [delete]
func (c *CargoController) DeleteCategory(ctx *gin.Context) {
	id := common.GetIDParam(ctx)
	if id == 0 {
		common.Error(ctx, common.ErrInvalidParams)
		return
	}

	// 获取当前用户ID
	userID := common.GetUserID(ctx)

	if err := c.cargoService.DeleteCategory(id, userID); err != nil {
		logger.Error("删除货物分类失败", zap.Error(err), zap.Uint("id", id))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, nil)
}

// GetCategory godoc
// @Summary 获取货物分类详情
// @Description 根据分类ID获取货物分类详细信息
// @Tags 货物分类
// @Accept json
// @Produce json
// @Param id path int true "分类ID"
// @Success 200 {object} common.Response{data=model.CargoCategory} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /api/v1/cargos/categories/{id} [get]
func (c *CargoController) GetCategory(ctx *gin.Context) {
	id := common.GetIDParam(ctx)
	if id == 0 {
		common.Error(ctx, common.ErrInvalidParams)
		return
	}

	category, err := c.cargoService.GetCategory(id)
	if err != nil {
		logger.Error("获取货物分类详情失败", zap.Error(err), zap.Uint("id", id))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, category)
}

// GetBatchCargos godoc
// @Summary 批量获取货物信息
// @Description 根据多个ID批量获取货物信息
// @Tags 货物管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param ids query string true "货物ID列表，逗号分隔"
// @Success 200 {object} resp.Response{data=[]model.Cargo} "成功"
// @Failure 400 {object} resp.Response "请求错误"
// @Failure 500 {object} resp.Response "内部错误"
// @Router /cargos/batch [get]
func (c *CargoController) GetBatchCargos(ctx *gin.Context) {
	idsParam := ctx.Query("ids")
	if idsParam == "" {
		common.Error(ctx, errors.New("未提供货物ID列表"))
		return
	}

	// 分割ID字符串
	idsStr := strings.Split(idsParam, ",")
	var ids []uint
	for _, idStr := range idsStr {
		id, err := strconv.ParseUint(idStr, 10, 32)
		if err != nil {
			logger.Warn("解析货物ID失败", zap.Error(err), zap.String("id", idStr))
			continue
		}
		ids = append(ids, uint(id))
	}

	if len(ids) == 0 {
		common.Error(ctx, errors.New("无有效的货物ID"))
		return
	}

	cargos, err := c.cargoService.GetBatchCargos(ids)
	if err != nil {
		logger.Error("批量获取货物信息失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	common.Success(ctx, cargos)
}
